using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using RAG.Domain.Configuration;
using RAG.Domain.Services;
using System.Text;
using System.Text.Json;

namespace RAG.Infrastructure.Services;

public class QwenEmbeddingService : IEmbeddingService
{
    private readonly HttpClient _httpClient;
    private readonly QwenApiSettings _settings;
    private readonly ILogger<QwenEmbeddingService> _logger;

    public QwenEmbeddingService(HttpClient httpClient, IOptions<QwenApiSettings> settings, ILogger<QwenEmbeddingService> logger)
    {
        _httpClient = httpClient;
        _settings = settings.Value;
        _logger = logger;

        // 通义千问API使用 Authorization: Bearer <api_key> 格式
        _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {_settings.ApiKey}");
    }

    // 统一：文本也使用多模态接口（仅提交文本）
    public async Task<float[]> GenerateTextEmbeddingAsync(string text)
    {
        // 调用多模态接口，contents 仅包含文本
        var textOnlyBytes = Array.Empty<byte>(); // 标记无图片
        return await GenerateMultimodalInternalAsync(textOnlyBytes, text, includeImage: false);
    }

    public async Task<float[]> GenerateMultimodalEmbeddingAsync(byte[] imageData, string? text = null)
        => await GenerateMultimodalInternalAsync(imageData, text, includeImage: true);

    private async Task<float[]> GenerateMultimodalInternalAsync(byte[] imageData, string? text, bool includeImage)
    {
        try
        {
            var contents = new List<object>();
            if (!string.IsNullOrWhiteSpace(text))
            {
                contents.Add(new { text });
            }
            if (includeImage && imageData.Length > 0)
            {
                var base64Image = Convert.ToBase64String(imageData);
                contents.Add(new { image = "data:image/jpeg;base64," + base64Image });
            }
            if (contents.Count == 0)
                throw new ArgumentException("必须提供文本或图片之一");

            var request = new
            {
                model = _settings.MultimodalEmbeddingModel,
                input = new { contents },
                parameters = new { }
            };
            var json = JsonSerializer.Serialize(request);
            var content = new StringContent(json, Encoding.UTF8, "application/json");

            _logger.LogDebug("[Embed] URL={Url} Model={Model} HasText={HasText} HasImage={HasImg} TextLen={TextLen}",
                _settings.MultimodalEmbeddingUrl, _settings.MultimodalEmbeddingModel, !string.IsNullOrWhiteSpace(text), includeImage && imageData.Length > 0, text?.Length ?? 0);

            var sw = System.Diagnostics.Stopwatch.StartNew();
            var response = await _httpClient.PostAsync(_settings.MultimodalEmbeddingUrl, content);
            if (!response.IsSuccessStatusCode)
            {
                var errorContent = await response.Content.ReadAsStringAsync();
                _logger.LogWarning("[Embed] Fail Status={Status} BodyLen={BodyLen} TextLen={TextLen}", (int)response.StatusCode, errorContent.Length, text?.Length ?? 0);
                throw new HttpRequestException($"多模态API失败: {response.StatusCode}: {errorContent}");
            }
            var responseJson = await response.Content.ReadAsStringAsync();
            sw.Stop();
            try
            {
                using var doc = JsonDocument.Parse(responseJson);
                var root = doc.RootElement;
                var embArr = root.GetProperty("output").GetProperty("embeddings");
                var dim = embArr[0].GetProperty("embedding").GetArrayLength();
                _logger.LogInformation("[Perf][Embed] Dim={Dim} ElapsedMs={Ms} HasImage={HasImg} TextLen={TextLen}", dim, sw.ElapsedMilliseconds, includeImage && imageData.Length > 0, text?.Length ?? 0);
            }
            catch (Exception ex)
            {
                _logger.LogDebug(ex, "解析嵌入响应统计失败");
            }
            var result = JsonSerializer.Deserialize<QwenMultimodalEmbeddingResponse>(responseJson, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
            var embedding = result?.Output?.Embeddings?.FirstOrDefault()?.Embedding;
            if (embedding == null || embedding.Length == 0)
                throw new InvalidOperationException($"多模态API未返回有效embedding: {responseJson}");
            return embedding;
        }
        catch (Exception ex)
        {
            throw new InvalidOperationException($"统一多模态嵌入失败: {ex.Message}", ex);
        }
    }
}


// 多模态API专用响应模型
public class QwenMultimodalEmbeddingResponse
{
    public QwenMultimodalOutput Output { get; set; } = new();
    public QwenMultimodalUsage? Usage { get; set; }
    public string RequestId { get; set; } = string.Empty;
}

public class QwenMultimodalOutput
{
    public List<QwenMultimodalEmbeddingItem> Embeddings { get; set; } = new();
}

public class QwenMultimodalEmbeddingItem
{
    public float[] Embedding { get; set; } = default!;
    public int Index { get; set; }
    public string Type { get; set; } = string.Empty;
}

public class QwenMultimodalUsage
{
    public int Duration { get; set; }
    public int ImageCount { get; set; }
    public int InputTokens { get; set; }
}

